route.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { NextRequest, NextResponse } from "next/server";
  2. import { z } from "zod";
  3. import { getSupabaseServerClient } from "@/lib/supabase/server";
  4. import { getSupabaseAdminClient } from "@/lib/supabase/admin";
  5. import { groupNameSchema } from "@/lib/groups/validation";
  6. import { deleteGroupAndData } from "@/lib/groups/delete-group";
  7. const renameSchema = z.object({ name: groupNameSchema });
  8. /** GET /api/groups/[id] — Get group details */
  9. export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
  10. try {
  11. const { id } = await params;
  12. const supabase = await getSupabaseServerClient();
  13. const {
  14. data: { user },
  15. } = await supabase.auth.getUser();
  16. if (!user) {
  17. return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  18. }
  19. const admin = getSupabaseAdminClient();
  20. const [{ data: membership }, { data: group, error }] = await Promise.all([
  21. admin
  22. .from("group_members")
  23. .select("role")
  24. .eq("group_id", id)
  25. .eq("user_id", user.id)
  26. .maybeSingle(),
  27. admin.from("groups").select("*").eq("id", id).single(),
  28. ]);
  29. if (!membership) {
  30. return NextResponse.json({ error: "Not a member of this group" }, { status: 403 });
  31. }
  32. if (error || !group) {
  33. return NextResponse.json({ error: "Group not found" }, { status: 404 });
  34. }
  35. return NextResponse.json({ group, role: membership.role });
  36. } catch {
  37. return NextResponse.json({ error: "Internal server error" }, { status: 500 });
  38. }
  39. }
  40. /** PATCH /api/groups/[id] — Rename group (admin only) */
  41. export async function PATCH(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
  42. try {
  43. const { id } = await params;
  44. const supabase = await getSupabaseServerClient();
  45. const {
  46. data: { user },
  47. } = await supabase.auth.getUser();
  48. if (!user) {
  49. return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  50. }
  51. const admin = getSupabaseAdminClient();
  52. const { data: membership } = await admin
  53. .from("group_members")
  54. .select("role")
  55. .eq("group_id", id)
  56. .eq("user_id", user.id)
  57. .maybeSingle();
  58. if (!membership || membership.role !== "admin") {
  59. return NextResponse.json({ error: "Admin access required" }, { status: 403 });
  60. }
  61. const body = await request.json();
  62. const parsed = renameSchema.safeParse(body);
  63. if (!parsed.success) {
  64. return NextResponse.json({ error: parsed.error.issues[0].message }, { status: 400 });
  65. }
  66. const { data: group, error } = await admin
  67. .from("groups")
  68. .update({ name: parsed.data.name })
  69. .eq("id", id)
  70. .select()
  71. .single();
  72. if (error || !group) {
  73. return NextResponse.json({ error: "Failed to rename group" }, { status: 500 });
  74. }
  75. return NextResponse.json({ group });
  76. } catch {
  77. return NextResponse.json({ error: "Internal server error" }, { status: 500 });
  78. }
  79. }
  80. /** DELETE /api/groups/[id] — Delete group (admin only) */
  81. export async function DELETE(
  82. _request: NextRequest,
  83. { params }: { params: Promise<{ id: string }> },
  84. ) {
  85. try {
  86. const { id } = await params;
  87. const supabase = await getSupabaseServerClient();
  88. const {
  89. data: { user },
  90. } = await supabase.auth.getUser();
  91. if (!user) {
  92. return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  93. }
  94. const admin = getSupabaseAdminClient();
  95. const { data: membership } = await admin
  96. .from("group_members")
  97. .select("role")
  98. .eq("group_id", id)
  99. .eq("user_id", user.id)
  100. .maybeSingle();
  101. if (!membership || membership.role !== "admin") {
  102. return NextResponse.json({ error: "Admin access required" }, { status: 403 });
  103. }
  104. await deleteGroupAndData(id);
  105. return NextResponse.json({ success: true });
  106. } catch {
  107. return NextResponse.json({ error: "Internal server error" }, { status: 500 });
  108. }
  109. }